const http = require('http');
const url = require('url');
const fs = require('fs');
const util = require('util');
const jsserverConf = require('./jsserver.conf');
 
let DEFAULT = {
	listenPort : 80,
 	listenIp : "127.0.0.1",
	suffix : "njs",
	httpDir : "E:\\oschina-git\\jsserver\\demo\\webA"
}

const mimetype = {
	'txt': 'text/plain',
	'htm': 'text/html',
	'html': 'text/html',
	'njs' : 'text/html',
	'css': 'text/css',
	'xml': 'application/xml',
	'json': 'application/json',
	'js': 'application/javascript',
	'jpg': 'image/jpeg',
	'jpeg': 'image/jpeg',
	'gif': 'image/gif',
	'png': 'image/png',
	'svg': 'image/svg+xml'
} 


const page_404 = function(req, res, path){
	res.writeHead(404, {
	  'Content-Type': 'text/html'
	});
	res.write('<!doctype html>\n');
	res.write('<title>404 Not Found</title>\n');
	res.write('<h1>Not Found</h1>');
	res.write(
	'<p>The requested URL ' +
	 path + 
	' was not found on this server.</p>'
	);
	res.end();
}

const page_500 = function(req, res, error){
	res.writeHead(500, {
	  'Content-Type': 'text/html'
	});

	res.write('<!doctype html>\n');
	res.write('<title>Internal Server Error</title>\n');
	res.write('<h1>Internal Server Error</h1>');
	res.write('<pre>' + util.inspect(error) + '</pre>');
}

const analysisRequest = function (str) { 
	if ( str === null ) return {}; 
	let queryArr = str.split("&"); 
	let get = {};
	queryArr.forEach((query)=> {
		let tempQuery = query.split("=");
		get[tempQuery[0]] = tempQuery[1];
	});
	return get;
}

const executeJS = function(req, res, filePath) {
	delete require.cache[require.resolve(filePath)]
	const jsCode = require(filePath); 
	res.writeHead(200, {
		 'Content-Type': mimetype[filePath.split('.').pop()] || 'text/plain'
	});
	let GET = analysisRequest(url.parse(req.url).query);
	let POST = {};
	try {
		jsCode.main(req, res, GET, POST);
	} catch(err) { 
		let stack = err.stack.replace(/\n/g,'<br/>');
		stack = stack.replace(/ /g,'&nbsp;');
		res.write( stack );
	}
	res.end();
}

const TIP = `
 _ __  ___  ___ _ ____   _____ _ __ 
| '_ \\/ __|/ _ \\ '__\\ \\ / / _ \\ '__|
| | | \\__ \\  __/ |   \\ V /  __/ |   
|_| |_|___/\\___|_|    \\_/ \\___|_|   
                                    
Server running at :
`
 
Array.prototype.unique = function(){
	var res = [];
	var json = {};
	for(var i = 0; i < this.length; i++){
		if(!json[this[i]]){
			res.push(this[i]);
			json[this[i]] = 1;
		}
	}
	return res;
}

//错误检查
if ( !jsserverConf.virtualHost || jsserverConf.virtualHost.length === 0 ) {
	throw('[\'VirtualHost\'] - this is required');
}

DEFAULT.listenPort = jsserverConf.listenPort || DEFAULT.listenPort;
DEFAULT.listenIp = jsserverConf.listenIp || DEFAULT.listenIp;
DEFAULT.suffix = jsserverConf.suffix || DEFAULT.suffix;

let countHost = [];
let server = [];
let hosts = {};

jsserverConf.virtualHost.forEach(function (item, index) {
	countHost.push(item.listenIp + ":" + item.listenPort);
})
let contHost = countHost.unique(); // 去重


contHost.forEach(function(item, index) {
	let tempArr = [];
	jsserverConf.virtualHost.forEach(function (item2, index2) { 
		if ( item === item2.listenIp + ":" + item2.listenPort ) {
			tempArr.push(item2); 
		}
	});
	hosts[item] = tempArr;
});

console.log(TIP); 

contHost.forEach(function(item, index) { 

	if ( hosts[item].constructor === Array ) { 
		server[index] = http.createServer(function (req, res) {
			let reqHost = req.headers.host.indexOf(':') === -1 ? req.headers.host + ":80" : req.headers.host;
			console.log(reqHost);
			hosts[item].forEach(function(hostItem) {  
				let hostItemHost = hostItem.host.map((item)=>{return item+":"+hostItem.listenPort}); 
				if ( hostItemHost.indexOf(reqHost) !== -1 ) {
					let urlSet  = url.parse(req.url);
					let realPath = hostItem.rootPath + urlSet.pathname;
					console.log((new Date()) + " : " + realPath);

					if ( urlSet.pathname[urlSet.pathname.length-1] === "/" ) { //判断该路径为目录

						for (var i = 0; i < hostItem.default.length; i++) {
							let newPath = realPath + hostItem.default[i];
							let isIndex = 0;
							if ( fs.existsSync(newPath) ) {
								let fileSuffix = newPath.split('.').pop();

								if ( fileSuffix === "njs" ) {

									executeJS(req, res, newPath);

								} else {

									let file = fs.createReadStream(newPath);
									res.writeHead(200, {
										 'Content-Type': mimetype[fileSuffix] || 'text/plain'
									});
									file.on('data', res.write.bind(res));
									file.on('close', res.end.bind(res));      
									file.on('error', function(err){
										return page_500(req, res, err);
									});

								} 
								isIndex++;
								break;  
							}
							if ( isIndex === 0 ) {
								return page_404(req, res, urlSet.pathname);
							}
						}

					} else { // 为文件

						let realPathArr = realPath.split('.');
						let fileSuffix = realPathArr.pop();
						if ( fileSuffix === hostItem.suffix ) {
							realPath = realPathArr.join() + "." + "njs";
							fileSuffix = "njs";
						}

						fs.exists(realPath, function(exists) { 
							if(!exists) {

								return page_404(req, res, urlSet.pathname);

							} else {

								if ( fileSuffix === "njs" ) {

									executeJS(req, res, realPath);

								} else {

									let file = fs.createReadStream(realPath);
									res.writeHead(200, {
										 'Content-Type': mimetype[fileSuffix] || 'text/plain'
									});
									file.on('data', res.write.bind(res));
									file.on('close', res.end.bind(res));      
									file.on('error', function(err){
										return page_500(req, res, err);
									});

								}

							}

						});
					}



				} 
			});   
		}).listen(item.split(':')[1], item.split(':')[0]);
		console.log(item);
	}
}); 